package kr.salebeans.cm.provider.customer.impl;

import java.util.List;

import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.persistence.Query;

import kr.salebeans.cm.customer.search.CustomerSearchCond;
import kr.salebeans.cm.customer.search.CustomerSearchCond.CustomerSearchType;
import kr.salebeans.cm.domain.customer.Customer;
import kr.salebeans.cm.provider.customer.CustomerProvider;
import kr.salebeans.cm.util.StringUtils;

public class CustomerProviderImpl implements CustomerProvider {

    @PersistenceContext
    private EntityManager em;

    /* (non-Javadoc)
     * @see kr.salebeans.cm.provider.customer.CustomerProvider#getCustomer(long)
     */
    @Override
    public Customer retrieveCustomer(long customerId) {
        return em.find(Customer.class, customerId);
    }

    /* (non-Javadoc)
     * @see kr.salebeans.cm.provider.customer.CustomerProvider#createCustomer(kr.salebeans.cm.domain.customer.Customer)
     */
    @Override
    public Customer createCustomer(Customer customer) {
        customer.createNewHandling();
        this.em.persist(customer);
        return customer;
    }

    /* (non-Javadoc)
     * @see kr.salebeans.cm.provider.customer.CustomerProvider#updateCustomer(kr.salebeans.cm.domain.customer.Customer)
     */
    @Override
    public Customer updateCustomer(Customer customer) {
        return this.em.merge(customer);
    }

    /* (non-Javadoc)
     * @see kr.salebeans.cm.provider.customer.CustomerProvider#retrieveCustomerList(kr.salebeans.cm.customer.search.CustomerSearchCond)
     */
    @SuppressWarnings("unchecked")
    @Override
    public List<Customer> retrieveCustomerList(CustomerSearchCond searchCond) {
        Query query = this.getRetrieveCustomerListQuery(searchCond, false);
        if (searchCond.isPagingYn()) {
            query.setFirstResult(searchCond.getFirstIndex());
            query.setMaxResults(searchCond.getMaxIndex());
        }
        return (List<Customer>) query.getResultList();
    }

    /* (non-Javadoc)
     * @see kr.salebeans.cm.provider.customer.CustomerProvider#retrieveTotalCustomerListCount(kr.salebeans.cm.customer.search.CustomerSearchCond)
     */
    @Override
    public long retrieveTotalCustomerListCount(CustomerSearchCond searchCond) {
        Query query = this.getRetrieveCustomerListQuery(searchCond, true);
        return (Long) query.getSingleResult();
    }

    private Query getRetrieveCustomerListQuery(CustomerSearchCond searchCond, boolean isCount) {
        StringBuilder qlString = new StringBuilder();
        if (isCount) qlString.append(" SELECT COUNT (c) ");
        else qlString.append(" SELECT c ");

        qlString.append(" FROM Customer c ");
        qlString.append(" WHERE c.shopId = :shopId ");
        qlString.append("   AND c.handling.useYn = 1 ");

        if (searchCond.getSearchType() != null || CustomerSearchType.ALL != searchCond.getSearchType()) {
            if (CustomerSearchType.GENDER == searchCond.getSearchType() && StringUtils.isNotBlank(searchCond.getGender())) {
                qlString.append(" AND c.gender = :gender ");
            }
            else if (CustomerSearchType.NAME == searchCond.getSearchType() && StringUtils.isNotBlank(searchCond.getName())) {
                qlString.append(" AND c.customerName = :customerName ");
            }
        }

        Query query = this.em.createQuery(qlString.toString());
        query.setParameter("shopId", searchCond.getShopId());

        if (searchCond.getSearchType() != null || CustomerSearchType.ALL != searchCond.getSearchType()) {
            if (CustomerSearchType.GENDER == searchCond.getSearchType() && StringUtils.isNotBlank(searchCond.getGender())) {
                query.setParameter("gender", searchCond.getGender());
            }
            else if (CustomerSearchType.NAME == searchCond.getSearchType() && StringUtils.isNotBlank(searchCond.getName())) {
                query.setParameter("customerName", searchCond.getName());
            }
        }

        if (!isCount) {
            qlString.append(" ORDER BY c.customerName DESC ");
        }
        return query;
    }

}
